package cn.tedu.medicalpath.order.service.impl;

import cn.tedu.medicalpath.base.constant.InspectionStatus;
import cn.tedu.medicalpath.base.constant.OrderPayStatus;
import cn.tedu.medicalpath.base.constant.OrderType;
import cn.tedu.medicalpath.base.constant.PrescriptionStatus;
import cn.tedu.medicalpath.base.exception.ServiceException;
import cn.tedu.medicalpath.base.response.StatusCode;
import cn.tedu.medicalpath.order.mapper.OrderMapper;
import cn.tedu.medicalpath.order.pojo.param.OrderSaveParam;
import cn.tedu.medicalpath.order.pojo.param.OrderQuery;
import cn.tedu.medicalpath.order.pojo.vo.OrderVO;
import cn.tedu.medicalpath.order.pojo.vo.PrescriptionOrderVO;
import cn.tedu.medicalpath.order.service.AlipayService;
import cn.tedu.medicalpath.order.service.OrderService;
import cn.tedu.medicalpath.prescription.mapper.PrescriptionMedicineMapper;
import cn.tedu.medicalpath.prescription.pojo.dto.PrescriptionMedicineQuery;
import cn.tedu.medicalpath.prescription.pojo.vo.PrescriptionMedicineVO;
import com.alipay.api.AlipayApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private PrescriptionMedicineMapper prescriptionMedicineMapper;

    @Autowired
    private AlipayService alipayService;

    @Override
    public List<OrderVO> findOrders(OrderQuery orderQuery) {
        //查询检查单列表
        List<OrderVO> inspectionsList = getInspectionOrderVOs(orderQuery);
        //查询处方单列表
        List<OrderVO> prescriptionList = getPrescriptionOrderVOs(orderQuery);
        //两个列表合并
        List<OrderVO> resultList = new ArrayList<>(inspectionsList);
        boolean addAllSuccess = resultList.addAll(prescriptionList);
        log.debug("合并两个列表是否成功：{}，结果：{}",addAllSuccess, resultList);
        return resultList;
    }

    private List<OrderVO> getInspectionOrderVOs(OrderQuery orderQuery) {
        List<OrderVO> inspectionsList =
                orderMapper.findInspectionsByPatientAndStatus(orderQuery);
        handleOrderVOList(inspectionsList, OrderType.INSPECTION);
        log.debug("查询检查单列表：{}", inspectionsList);
        return inspectionsList;
    }

    private List<OrderVO> getPrescriptionOrderVOs(OrderQuery orderQuery) {
        List<OrderVO> prescriptionList =
                orderMapper.findPrescriptionsByPatientAndStatus(orderQuery);
        handleOrderVOList(prescriptionList, OrderType.PRESCRIPTION);
        log.debug("查询处方单列表：{}", prescriptionList);
        return prescriptionList;
    }

    private void handleOrderVOList(List<OrderVO> orderVOList, String type) {
        orderVOList.forEach(orderVO -> {
            orderVO.setType(type);
            String doctorName = orderMapper.findDoctorNameById(orderVO.getDoctorId());
            orderVO.setDoctorName(doctorName);
            log.debug("处理订单支付VO，给医生名赋值，订单类型：{}，医生名：{}", type, doctorName);
        });
    }

    @Override
    public void payOrder(OrderSaveParam orderSaveParam) {
        String type = orderSaveParam.getType();
        String status = orderSaveParam.getStatus();
        Long id = orderSaveParam.getId();
        //先判断订单类型，类型不正确则抛出异常
        if (!OrderType.INSPECTION.equals(type) && !OrderType.PRESCRIPTION.equals(type)) {
            log.error("支付失败，未知的订单类型：{}", type);
            throw new ServiceException(StatusCode.FAILED);
        }
        //再判断支付状态，医保支付和普通支付则调用相应方法，状态不正确则抛出异常
        if (OrderPayStatus.INSURANCE_PAYED.equals(status)) {
            //医保支付
            Integer insurancePrice = orderSaveParam.getInsurancePrice();
            insurancePay(id,type,insurancePrice);
        }else if (OrderPayStatus.COMMON_PAYED.equals(status)) {
            //普通支付
            Integer price = orderSaveParam.getPrice();
            try {
                commonPay(id,type,price);
            } catch (AlipayApiException e) {
                log.error("支付宝支付失败，异常信息：{}", e.getMessage());
                throw new ServiceException(StatusCode.ALIPAY_FAILED);
            }
        }else {
            log.error("支付失败，未知的订单支付状态：{}", status);
            throw new ServiceException(StatusCode.FAILED);
        }
    }

    private void insurancePay(Long id, String type, Integer insurancePrice) {
        //判断是检查单或处方单
        if (OrderType.INSPECTION.equals(type)) {
            //检查单
            log.debug("用医保支付检查单开始，id：{}，金额：{}", id, insurancePrice);
            //todo 调用医保局支付接口，再进行回调
            orderMapper.payInspection(id, InspectionStatus.INSURANCE_PAYED);
            log.debug("用医保支付检查单成功，id：{}，金额：{}", id, insurancePrice);
        }else {
            //处方单
            log.debug("用医保支付处方单开始，id：{}，金额：{}", id, insurancePrice);
            //todo 调用医保局支付接口，再进行回调
            orderMapper.payPrescription(id, PrescriptionStatus.INSURANCE_PAYED);
            log.debug("用医保支付处方单成功，id：{}，金额：{}", id, insurancePrice);
        }
    }

    private void commonPay(Long id, String type, Integer price) throws AlipayApiException {
        //判断是检查单或处方单
        if (OrderType.INSPECTION.equals(type)) {
            //检查单
            log.debug("普通支付检查单开始，id：{}，金额：{}", id, price);
            //调用阿里支付接口
            Boolean success = alipayService.alipay(id, type, price);
            if (success) {
                //todo 应该改为阿里进行回调后再修改状态
                orderMapper.payInspection(id, InspectionStatus.COMMON_PAYED);
                log.debug("普通支付检查单成功，id：{}，金额：{}", id, price);
            }else {
                log.error("普通支付检查单失败，id：{}，金额：{}", id, price);
                throw new ServiceException(StatusCode.ALIPAY_FAILED);
            }
        }else {
            //处方单
            log.debug("普通支付处方单开始，id：{}，金额：{}", id, price);
            //调用阿里支付接口
            Boolean success = alipayService.alipay(id, type, price);
            if (success) {
                //todo 应该改为阿里进行回调后再修改状态
                orderMapper.payPrescription(id, PrescriptionStatus.COMMON_PAYED);
                log.debug("普通支付处方单成功，id：{}，金额：{}", id, price);
            }else {
                log.error("普通支付处方单失败，id：{}，金额：{}", id, price);
                throw new ServiceException(StatusCode.ALIPAY_FAILED);
            }
        }
    }

    @Override
    public List<PrescriptionOrderVO> findPrescriptionOrdersAndSubMedicines
            (OrderQuery orderQuery) {
        List<PrescriptionOrderVO> resultList = new ArrayList<>();
        //查询处方单列表
        List<OrderVO> prescriptionList = getPrescriptionOrderVOs(orderQuery);
        for (OrderVO orderVO : prescriptionList){
            if (PrescriptionStatus.NOT_PAYED.equals(orderVO.getStatus())) break;
            PrescriptionOrderVO prescriptionOrderVO = new PrescriptionOrderVO();
            BeanUtils.copyProperties(orderVO, prescriptionOrderVO);
            prescriptionOrderVO.setMedicineVOList(
                    getPrescriptionMedicineVOs(orderVO.getId()));
            resultList.add(prescriptionOrderVO);
        }
        return resultList;
    }

    private List<PrescriptionMedicineVO> getPrescriptionMedicineVOs(Long id) {
        PrescriptionMedicineQuery prescriptionMedicineQuery = new PrescriptionMedicineQuery();
        prescriptionMedicineQuery.setPrescriptionId(id);
        return prescriptionMedicineMapper.selectPrescriptionMedicine(prescriptionMedicineQuery);
    }
}
